/*
 * GL.cpp
 *
 *  Created on: Feb 11, 2011
 *      Author: alki
 */

#include "manager/MaterialManager.h"
#include "GL.h"
#include <SDL/SDL.h>

GL::GL() {
	/* Enable smooth shading */
	glShadeModel( GL_SMOOTH );

	/* Set the background black */
	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

	/* Depth buffer setup */
	glClearDepth( 1.0f );

	/* Enables Depth Testing */
	glEnable( GL_DEPTH_TEST );

	/* The Type Of Depth Test To Do */
	glDepthFunc( GL_LEQUAL );

	/* Really Nice Perspective Calculations */
	glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
}

GL::~GL() {
}

void GL::SetResolution(int width,int height) {
	this->m_width = width;
	this->m_height = height;

    /* Height / width ration */
    GLfloat ratio;

    /* Protect against a divide by zero */
    if ( height == 0 )
	height = 1;

    ratio = ( GLfloat )width / ( GLfloat )height;

    /* Setup our viewport. */
    glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );

    /* change to the projection matrix and set our viewing volume. */
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity( );

    /* Set our perspective */
    gluPerspective( 45.0f, ratio, 0.1f, 100.0f );

    /* Make sure we're chaning the model view and not the projection */
    glMatrixMode( GL_MODELVIEW );

    /* Reset The View */
    glLoadIdentity( );
}

void GL::TestDraw() {
	// Clear The Screen And The Depth Buffer
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	glLoadIdentity();

	glBegin( GL_QUADS );                // Draw A Quad
	  glVertex3f( -1.0f,  1.0f, -5 ); // Top Left
	  glVertex3f(  1.0f,  1.0f, -5 ); // Top Right
	  glVertex3f(  1.0f, -1.0f, -5 ); // Bottom Right
	  glVertex3f( -1.0f, -1.0f, -5 ); // Bottom Left
	glEnd( );                           // Done Drawing The Quad

	// Draw it to the screen
	SDL_GL_SwapBuffers( );
}

void GL::DrawObject(Objekt* obj,const MaterialManager &matman) {
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
    gluPerspective( 45.0f, this->m_width/this->m_height, 0.01f, 100.0f );
    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

	glRotatef(obj->getRotX(),1.0f,0.0f,0.0f);
	glRotatef(obj->getRotY(),0.0f,1.0f,0.0f);
	glRotatef(obj->getRotZ(),0.0f,0.0f,1.0f);

	glTranslatef(obj->getPosition().getX(),obj->getPosition().getY(),obj->getPosition().getZ());

	glBegin( GL_TRIANGLES );
	for(int i=0;i<obj->getTriangleCount();i++) {
		for(int j=0;j<3;j++) {
			glColor3f(matman.getMaterial(obj->getVertex(obj->getTriangle(i).points[j]).mat)->getLightEmissive().r,
					matman.getMaterial(obj->getVertex(obj->getTriangle(i).points[j]).mat)->getLightEmissive().g,
					matman.getMaterial(obj->getVertex(obj->getTriangle(i).points[j]).mat)->getLightEmissive().b);
			glVertex3f(obj->getVertex(obj->getTriangle(i).points[j]).pos.getX(),
					obj->getVertex(obj->getTriangle(i).points[j]).pos.getY(),
					obj->getVertex(obj->getTriangle(i).points[j]).pos.getZ());
		}
	}
	glEnd( );
}

void GL::DrawPoint(int x,int y,float r,float g,float b) {
	if(x>this->m_width || x<0 || y>this->m_height || y<0)
		return;

	glColor3f(r,g,b);
	glVertex2i(x,y);
}

void GL::DrawLine(float x1,float y1,float z1,float x2,float y2,float z2,float r,float g,float b) {
	glLoadIdentity();
	glColor3f(r,g,b);
	glBegin(GL_LINES);
	glVertex3f(x1,y1,z1);
	glVertex3f(x2,y2,z2);
	glEnd();
}

void GL::DrawRay(Gerade *ray) {
	DrawLine(ray->getPos().getX(),
			ray->getPos().getY(),
			-ray->getPos().getZ(),
			ray->getDir().getX()*1000,
			ray->getDir().getY()*1000,
			ray->getDir().getZ()*1000,
			1,1,0);
}

void GL::BeginDraw() {
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}

void GL::BeginPoints() {
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glOrtho(0,this->m_width,this->m_height,0,-1,1);

	glMatrixMode(GL_MODELVIEW);						// Select The Modelview Matrix
	glLoadIdentity();							// Reset The Modelview Matrix
	glPointSize(1);

	glBegin(GL_POINTS);
}

void GL::EndDraw(){
	glFlush();
	SDL_GL_SwapBuffers( );
}

void GL::EndPoints() {
	glEnd();
}
